home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Tool Chest / Dev.CD Feb 97 TC.toast / Sample Code / Interapplication Communication / MenuScripter 4.0 / Sources / MSAESetData.c < prev    next >
Encoding:
Text File  |  1996-07-09  |  28.3 KB  |  1,138 lines  |  [TEXT/CWIE]

  1. // MSAESetData.c
  2. //
  3. // Original version by Jon Lansdell and Nigel Humphreys.
  4. // 4.0 and 3.1 updates by Greg Sutton.
  5. // ©Apple Computer Inc 1996, all rights reserved.
  6.  
  7. /*
  8.         Changes for 4.0
  9.  
  10.         29-Feb-96 : GS : Added abiltiy to set properties from menus and menu items.
  11.         29-Feb-96 : GS : Added script properties to application and document objects.
  12. */
  13.  
  14. #include "MSAESetData.h"
  15.  
  16. #include "MSWindow.h"
  17. #include "MSGlobals.h"
  18. #include "MSAEUtils.h"
  19. #include "MSAETextUtils.h"
  20. #include "MSAEWindowUtils.h"
  21. #include "MSAEMenuUtils.h"
  22. #include "MSAppleEvents.h"
  23.  
  24. #include "MSAESelect.h"
  25. #include "MSScript.h"
  26. #include "MSAECreate.h"
  27.  
  28. #ifdef THINK_C
  29.     #include "PLStrs.h"
  30. #else
  31.     #include <PLStringFuncs.h>
  32. #endif
  33. #include <string.h>
  34.  
  35.     // Prototypes
  36. void    SendwCalcRgnsToWind( WindowPtr wP );
  37.  
  38.  
  39. // --------------------------------------------------------------------------
  40. //    Name:             DoSetData
  41. //    Purpose:        Handles the SetData Apple Event, extracting the direct
  42. //                    object (which says what to set) and the data (what to set
  43. //                    it to).
  44. // --------------------------------------------------------------------------
  45.      
  46. pascal OSErr    DoSetData(const AppleEvent    *theAppleEvent,
  47.                                 AppleEvent    *reply,
  48.                                 long        handlerRefCon)
  49. {
  50. #ifdef __MWERKS__
  51.     #pragma unused (reply, handlerRefCon)
  52. #endif
  53.     
  54.     AEDesc     directObj = {typeNull, NULL},
  55.             dataDesc = {typeNull, NULL};
  56.     OSErr      err;
  57.             
  58.         // pick up the direct object, which is the object whose data is to be set
  59.     err = AEGetParamDesc(theAppleEvent,  keyDirectObject,
  60.                                     typeWildCard, &directObj);
  61.     if (noErr != err) goto done;
  62.         
  63.         // now the data to set it to - typeWildCard means get as is
  64.         // e.g. this is the name of the font for text
  65.     err = AEGetParamDesc(theAppleEvent, keyAEData, typeWildCard, &dataDesc);
  66.     if (noErr != err) goto done;
  67.     
  68.         // missing any parameters?
  69.     err = GotRequiredParams(theAppleEvent);
  70.     if (noErr != err) goto done;
  71.     
  72.         // set the data
  73.     err = HandleSetData(&directObj, &dataDesc);
  74.  
  75. done:            
  76.     (void)AEDisposeDesc(&directObj);
  77.     (void)AEDisposeDesc(&dataDesc);
  78.  
  79.     return(err);
  80. }    // DoSetData
  81.  
  82.  
  83. // ---------------------------------------------------------------------------
  84. //        Name:             HandleSetData
  85. //        Purpose:        Resolves the object into a token (could be one of 
  86. //                        many) andthe sets the data of that object to dataDesc.
  87. // ---------------------------------------------------------------------------
  88.      
  89. OSErr HandleSetData(const AEDesc *theObj, AEDesc *dataDesc)
  90. {
  91.     TextToken       theTextToken;
  92.     Size            tokenSize;
  93.     AEDesc          objTokenDesc = {typeNull, NULL},
  94.                     itemDesc = {typeNull, NULL},
  95.                     ignoreResult = {typeNull, NULL};
  96.     long            index;
  97.     DescType        returnedType;
  98.     OSErr           err;
  99.  
  100.         //    Coerce theObj into a token which we can use - 
  101.         //   set the property or data for that token
  102.     if ( typeObjectSpecifier == theObj->descriptorType )
  103.         err = AEResolve( theObj, kAEIDoMinimum, &objTokenDesc );
  104.     else if ( typeNull != theObj->descriptorType )    // Otherwise, just copy it
  105.         err = AEDuplicateDesc( theObj, &objTokenDesc );
  106.  
  107.     if (noErr != err) goto done;
  108.             
  109.     switch (objTokenDesc.descriptorType)
  110.     {
  111.         case typeMyApplProp:
  112.             err = SetApplicationProperty( &objTokenDesc, dataDesc );
  113.             break;
  114.     
  115.         case typeMyWindowProp:
  116.             err = SetWindowProperty(&objTokenDesc, dataDesc);
  117.             break;
  118.         
  119.         case typeMyDocumentProp:
  120.             err = SetDocumentProperty(&objTokenDesc, dataDesc);
  121.             break;
  122.             
  123.         case typeMyMenuProp:
  124.             err = SetMenuProperty( &objTokenDesc, dataDesc );
  125.             break;
  126.             
  127.         case typeMyMenuItemProp:
  128.             err = SetMenuItemProperty( &objTokenDesc, dataDesc );
  129.             break;
  130.         
  131.         case typeMyTextProp:
  132.             err = SetTextProperty(&objTokenDesc, dataDesc);
  133.             break;
  134.             
  135.         case typeMyText:
  136.             GetRawDataFromDescriptor(&objTokenDesc,  (Ptr)&theTextToken,
  137.                                             sizeof(theTextToken), &tokenSize);
  138.             
  139.                         // itemDesc is a null descriptor here
  140.             err = CreateAtTextToken(cText, dataDesc, &theTextToken,
  141.                                                     &itemDesc, &ignoreResult);
  142.             break;
  143.  
  144.         case typeAEList:                // If it's a list then do each item
  145.             err = AECountItems(&objTokenDesc, &index);
  146.             if (noErr != err) goto done;
  147.  
  148.             for (; index > 0; index--)
  149.             {
  150.                 err = AEGetNthDesc(&objTokenDesc, index, typeWildCard, &returnedType, &itemDesc);
  151.  
  152.                 if (noErr == err)        // Get property by calling this function again
  153.                     err = HandleSetData(&itemDesc, dataDesc);
  154.                 
  155.                 if (itemDesc.dataHandle)
  156.                     AEDisposeDesc(&itemDesc);
  157.             }
  158.             break;
  159.             
  160.         default:
  161.             err = errAEWrongDataType;
  162.     }
  163.  
  164. done:
  165.     (void)AEDisposeDesc( &objTokenDesc );
  166.     (void)AEDisposeDesc( &itemDesc );
  167.     (void)AEDisposeDesc( &ignoreResult );
  168.  
  169.     return err;
  170. } // HandleSetData
  171.  
  172.  
  173.  
  174. OSErr    SetApplicationProperty( const AEDesc *theTokenDesc, const AEDesc *dataDesc )
  175. {
  176.     AppPropToken    aToken;
  177.     AEDesc          aDesc = {typeNull, NULL};
  178.     Size            tokenSize;
  179.     OSErr           err;
  180.  
  181.     err = AECoerceDesc( theTokenDesc, typeMyApplProp, &aDesc );
  182.     if (noErr != err) goto done;
  183.  
  184.     GetRawDataFromDescriptor( &aDesc, (Ptr)&aToken,
  185.                                     sizeof( aToken ), &tokenSize );
  186.     
  187.     SetApplicationTokenProperty( &aToken, dataDesc );
  188.     
  189. done:
  190.     (void)AEDisposeDesc(&aDesc);
  191.     
  192.     return(err);
  193. } // SetApplicationProperty
  194.  
  195.  
  196. OSErr    SetApplicationTokenProperty( AppPropToken* theToken, const AEDesc *dataDesc )
  197. {
  198.     OSErr           err;
  199.     
  200.     switch ( theToken->tokenProperty )
  201.     {
  202.         case pScript:
  203.             err = SetScriptDesc( dataDesc, &gAppRec.theScriptID );
  204.             break;
  205.     
  206.         default:    
  207.             err = errAEEventNotHandled;
  208.     }
  209.     
  210.     return err;
  211. }
  212.  
  213.  
  214. OSErr    SetWindowSelectionProperty(WindowPtr theWindow, const AEDesc *dataDesc)
  215. {
  216.     AEDesc        textDesc = {typeNull, NULL},
  217.                 ignoreResult = {typeNull, NULL};
  218.     TextToken    aTextToken;
  219.     Size        actualSize;
  220.     short        ignore;
  221.     OSErr        err;
  222.         
  223.     // first check to see if we are dealing with a TEXT descriptor or
  224.     // an object specifier. Since AECoerceDesc will end up calling
  225.     // AEResolve, we don't want to call this if the user entered something
  226.     // like 'Set selection of window 1 to "some text"
  227.  
  228.     switch (dataDesc->descriptorType)
  229.     {
  230.         case typeChar:
  231.         case typeIntlText:
  232.         case typeStyledText:
  233.             err = GetWindowSelection(theWindow, &aTextToken, &ignore);
  234.             if (noErr != err) goto done;
  235.  
  236.                         // textDesc is a null descriptor here
  237.             err = CreateAtTextToken(cText, dataDesc, &aTextToken,
  238.                                                     &textDesc, &ignoreResult);
  239.             break;
  240.             
  241.         default:     // we are dealing with an object specifier
  242.             err = AECoerceDesc(dataDesc, typeMyText, &textDesc);
  243.             if (noErr != err) goto done;
  244.             
  245.             GetRawDataFromDescriptor(&textDesc, (Ptr)&aTextToken, sizeof(aTextToken),
  246.                                             &actualSize);
  247.                                             
  248.             SelectTextToken(&aTextToken);
  249.     }
  250.  
  251. done:
  252.     (void)AEDisposeDesc(&textDesc);
  253.  
  254.     return(err);
  255. }
  256.  
  257.  
  258. void    SendwCalcRgnsToWind( WindowPtr wP )
  259. {
  260. // This forces a wCalcRgns message to be sent to the windows proc!! Ughhhhhhh.....
  261.     Handle                  h;
  262.     long                    param = 0;
  263.     SInt8                   hState;
  264.  
  265.     h = (*(WindowPeek)wP).windowDefProc;
  266.     hState = HGetState(h);
  267.     HLock(h);       // paranoia?
  268.  
  269.     CallWindowDefProc((WindowDefProcPtr)*h, documentProc, wP, wCalcRgns, param);
  270.  
  271.     HSetState(h, hState);
  272. }
  273.  
  274.  
  275. OSErr    SetWindowProperty( const AEDesc *theTokenDesc, const AEDesc *dataDesc )
  276. {
  277.     WindowPropToken theWindowPropToken;
  278.     AEDesc          aDesc = {typeNull, NULL};
  279.     Size            tokenSize;
  280.     OSErr            err;
  281.  
  282.     err = AECoerceDesc( theTokenDesc, typeMyWindowProp, &aDesc );
  283.     if (noErr != err) goto done;
  284.  
  285.     GetRawDataFromDescriptor( &aDesc, (Ptr)&theWindowPropToken,
  286.                                     sizeof(theWindowPropToken), &tokenSize );
  287.                                     
  288.     err = SetWindowTokenProperty( &theWindowPropToken, dataDesc );
  289.  
  290. done:
  291.     (void)AEDisposeDesc( &aDesc );
  292.  
  293.     return err;
  294. }
  295.  
  296.  
  297. // ------------------------------------------------------------------------
  298. //    Name:         SetWindowTokenProperty
  299. //    Purpose:    Sets the window property specified in theToken to
  300. //                be that supplied in dataDesc.
  301. // ------------------------------------------------------------------------
  302.  
  303. OSErr    SetWindowTokenProperty( WindowPropToken* theToken, const AEDesc* theData )
  304. {
  305.     Rect        aRect,
  306.                 strucRect,
  307.                 contRect;
  308.     Boolean        aBoolean;
  309.     Str255        aString;
  310.     long        aLong;
  311.     GrafPtr        aPort;
  312.     WindowPeek    aWindowPeek;
  313.     OSErr        err = noErr;
  314.     
  315.     switch (theToken->tokenProperty)
  316.     {
  317.         case pBounds:
  318.             err = GetRectFromDescriptor( theData, &aRect );
  319.             if ( noErr != err ) goto done;
  320.             
  321.             err = GetWindowBounds( theToken->tokenWindowToken.tokenWindow, &strucRect );
  322.                 // Don't set bounds if they're the same as before
  323.             if ( noErr != err || EqualRect( &aRect, &strucRect ) ) goto done;
  324.             
  325.             aWindowPeek = (WindowPeek)theToken->tokenWindowToken.tokenWindow;
  326.  
  327.             aBoolean = IsVisible( theToken->tokenWindowToken.tokenWindow );
  328.  
  329.             if ( ! aBoolean )
  330.                 SendwCalcRgnsToWind( theToken->tokenWindowToken.tokenWindow );
  331.             
  332.             strucRect = (*aWindowPeek->strucRgn)->rgnBBox;
  333.             contRect = (*aWindowPeek->contRgn)->rgnBBox;
  334.  
  335.             // the rectangle is for the structure region, and is in global coordinates
  336.             // MoveWindow and SizeWindow apply to the content region, so we have to massage a little
  337.  
  338.             aRect.top    += contRect.top - strucRect.top;
  339.             aRect.left   += contRect.left - strucRect.left;
  340.             aRect.bottom -= strucRect.bottom - contRect.bottom;
  341.             aRect.right  -= strucRect.right - contRect.right;
  342.             
  343.             if ( EmptyRect( &aRect ) ) 
  344.                 err = errAECorruptData;
  345.             else
  346.             {
  347.                 if ( aBoolean )        // IsVisible
  348.                 {
  349.                     MoveWindow( theToken->tokenWindowToken.tokenWindow,
  350.                                          aRect.left,
  351.                                          aRect.top,
  352.                                          false );
  353.                     SizeWindow( theToken->tokenWindowToken.tokenWindow,
  354.                                          aRect.right - aRect.left,
  355.                                          aRect.bottom - aRect.top,
  356.                                          true );
  357.                 }
  358.                 else
  359.                 {            // Move offscreen first
  360.                     MoveWindow( theToken->tokenWindowToken.tokenWindow,
  361.                                          10000,
  362.                                          10000,
  363.                                          false );
  364.  
  365.                             // Encapsulate the resizing in Show then Hide
  366.                     ShowWindow( theToken->tokenWindowToken.tokenWindow );
  367.                     SizeWindow( theToken->tokenWindowToken.tokenWindow,
  368.                                          aRect.right - aRect.left,
  369.                                          aRect.bottom - aRect.top,
  370.                                          true );
  371.                     HideWindow( theToken->tokenWindowToken.tokenWindow );
  372.  
  373.                             // Move it to the proper place
  374.                     MoveWindow( theToken->tokenWindowToken.tokenWindow,
  375.                                          aRect.left,
  376.                                          aRect.top,
  377.                                          false );
  378.                 }
  379.  
  380.                 GetPort( &aPort );
  381.                 SetPort( theToken->tokenWindowToken.tokenWindow );
  382.                 ResizeWindow( DPtrFromWindowPtr( theToken->tokenWindowToken.tokenWindow ) );
  383.                 SetPort( aPort );
  384.             }
  385.             break;
  386.  
  387.         case pVisible:
  388.             err = GetBooleanFromDescriptor(theData, &aBoolean);
  389.             if (noErr != err) goto done;
  390.  
  391.             if (aBoolean)
  392.                 ShowMSWindow(theToken->tokenWindowToken.tokenWindow);
  393.             else
  394.                 HideMSWindow(theToken->tokenWindowToken.tokenWindow);
  395.             break;
  396.  
  397.         case pIsZoomed:
  398.             GetPort( &aPort );
  399.             SetPort( theToken->tokenWindowToken.tokenWindow );
  400.             err = GetBooleanFromDescriptor( theData, &aBoolean );
  401.             if ( aBoolean )
  402.                 ZoomWindow( qd.thePort, inZoomOut, false );
  403.             else
  404.                 ZoomWindow( qd.thePort, inZoomIn, false );
  405.                                                      
  406.             ResizeWindow( DPtrFromWindowPtr( theToken->tokenWindowToken.tokenWindow ) );
  407.             SetPort( aPort );
  408.             break;
  409.  
  410.         case pName:
  411.             err = GetPStringFromDescriptor(theData, aString);
  412.             if (noErr != err) goto done;
  413.             
  414.             SetWTitle(theToken->tokenWindowToken.tokenWindow, aString);
  415.             break;
  416.             
  417.         case pIndex:
  418.             err = GetLongIntFromDescriptor(theData, &aLong);
  419.             if (noErr != err) goto done;
  420.             
  421.             SetWindowIndex( theToken->tokenWindowToken.tokenWindow, aLong );
  422.             break;
  423.  
  424.         case pBestType:
  425.         case pClass:
  426.         case pDefaultType:
  427.         case pHasCloseBox:
  428.         case pIsZoomable:
  429.             err = errAEEventNotHandled;
  430.             break;
  431.             
  432.         default:
  433.             err = errAEEventNotHandled;
  434.     }
  435.  
  436. done:    
  437.     return(err);
  438. }
  439.  
  440.  
  441. OSErr    SetDocumentProperty( const AEDesc *theTokenDesc, const AEDesc *dataDesc )
  442. {
  443.     WindowPropToken theWindowPropToken;
  444.     AEDesc          aDesc = {typeNull, NULL};
  445.     Size            tokenSize;
  446.     OSErr           err;
  447.  
  448.     err = AECoerceDesc( theTokenDesc, typeMyDocumentProp, &aDesc );
  449.     if (noErr != err) goto done;
  450.  
  451.     GetRawDataFromDescriptor( &aDesc, (Ptr)&theWindowPropToken,
  452.                                     sizeof(theWindowPropToken), &tokenSize );
  453.     
  454.     SetDocumentTokenProperty( &theWindowPropToken, dataDesc );
  455.     
  456. done:
  457.     (void)AEDisposeDesc(&aDesc);
  458.     
  459.     return(err);
  460. } // SetDocumentProperty
  461.  
  462.  
  463. OSErr    SetDocumentTokenProperty( WindowPropToken* theToken, const AEDesc *dataDesc )
  464. {
  465.     Str255          aPStr;
  466.     DPtr            theDocument;
  467.     THPrint         theTHPrint;
  468.     TextToken        aTextToken;
  469.     Boolean            aBoolean;
  470.     AEDesc            nullDesc = {typeNull, NULL},
  471.                     aDesc = {typeNull, NULL};
  472.     Handle          hGXJobData;
  473.     OSErr           err = noErr;
  474.     
  475.     theDocument = DPtrFromWindowPtr( theToken->tokenWindowToken.tokenWindow );
  476.     
  477.     switch ( theToken->tokenProperty )
  478.     {
  479.         case pName:
  480.             err = GetPStringFromDescriptor( dataDesc, aPStr );
  481.             if (noErr != err) goto done;
  482.  
  483.             if ( aPStr[0] == 0) 
  484.                 err = errAEWrongDataType;
  485.             else
  486.             {
  487.                 SetWTitle( theToken->tokenWindowToken.tokenWindow, aPStr );
  488.                 PLstrcpy( theDocument->theFileName, aPStr ); // Should we do this???
  489.             }
  490.             break;
  491.  
  492.         case pText:
  493.         case pContents:
  494.                             // Get whole window as place to insert data
  495.             err = TextTokenFromDocumentToken(&(theToken->tokenWindowToken), &aTextToken);
  496.             if (noErr != err) goto done;
  497.  
  498.             err = CreateAtTextToken( cText, dataDesc, &aTextToken,
  499.                                                     &nullDesc, &aDesc );
  500.             break;
  501.  
  502.         case pIsModified:
  503.             err = GetBooleanFromDescriptor( dataDesc, &aBoolean );
  504.             if (noErr != err) goto done;
  505.         
  506.             theDocument->dirty = aBoolean;
  507.             goto done;    // Don't set dirty flag again
  508.             
  509.         case pPageSetup:
  510.             if ( ! gGXIsPresent )
  511.             {
  512.                 err = GetTHPrintFromDescriptor(dataDesc, &theTHPrint);
  513.                     
  514.                 if (theTHPrint) 
  515.                 {
  516.                     if (theDocument->thePrintSetup) 
  517.                         DisposHandle((Handle)theDocument->thePrintSetup);
  518.                         
  519.                     theDocument->thePrintSetup = theTHPrint;
  520.                     
  521.                     ResizePageSetupForDocument(theDocument);
  522.                 }
  523.             }
  524.             else
  525.                 err = errAEEventNotHandled;                     
  526.             break;
  527.             
  528.         case pGXPageSetup:
  529.             if ( gGXIsPresent )
  530.             {
  531.                 err = AECoerceDesc(dataDesc,typeTGXPrint,&aDesc);
  532.     
  533.                 hGXJobData = nil;
  534.     
  535.                 if (err==noErr) 
  536.                 {
  537.                     hGXJobData = NewHandle(GetHandleSize(aDesc.dataHandle));
  538.     
  539.                     BlockMove(*(aDesc.dataHandle),
  540.                                         *hGXJobData,
  541.                                         GetHandleSize(aDesc.dataHandle));
  542.                 }
  543.                     
  544.                 if (hGXJobData) 
  545.                 {
  546.                     GXUnflattenJobFromHdl(theDocument->documentJob, hGXJobData);
  547.                     err = GXGetJobError(theDocument->documentJob);
  548.                     
  549.                     ResizePageSetupForDocument(theDocument);
  550.                 }
  551.             }
  552.             else
  553.                 err = errAEEventNotHandled;                     
  554.             break;
  555.             
  556.         case pSelection:
  557.             err = SetWindowSelectionProperty(theToken->tokenWindowToken.tokenWindow, dataDesc);
  558.             break;
  559.     
  560.         case pScript:
  561.             err = SetScriptDesc( dataDesc, &theDocument->theScriptID );
  562.             break;
  563.  
  564.         default:    
  565.             err = SetWindowTokenProperty( theToken, dataDesc );
  566.     }
  567.     
  568.     if ( noErr == err && pIsModified != theToken->tokenProperty)
  569.         theDocument->dirty = true;
  570.     
  571. done:
  572.     (void)AEDisposeDesc( &nullDesc );
  573.     (void)AEDisposeDesc( &aDesc );
  574.     
  575.     return(err);
  576. }
  577.  
  578. OSErr    GetTHPrintFromDescriptor(const AEDesc *sourceDesc, THPrint *result)
  579. {
  580.     Size    ptSize;
  581.     AEDesc  resultDesc;
  582.     OSErr   err;
  583.     
  584.     *result = NULL;
  585.     
  586.     err = AECoerceDesc(sourceDesc, typeTPrint, &resultDesc);
  587.     if (noErr != err) goto done;
  588.     
  589.     *result = (THPrint)NewHandle(sizeof(TPrint));
  590.     
  591.     PrOpen();
  592.     PrintDefault(*result);
  593.     
  594.     HLock((Handle)*result);
  595.     GetRawDataFromDescriptor(&resultDesc, (Ptr)**result, sizeof(TPrint), &ptSize);
  596.     HUnlock((Handle)*result);
  597.     
  598.     if ((ptSize<sizeof(TPrint)) || (PrValidate(*result)))
  599.     {
  600.         err = errAECoercionFail;
  601.         DisposHandle((Handle)*result);
  602.         *result = NULL;
  603.     }
  604.     
  605.     PrClose();
  606.  
  607. done:    
  608.     if (resultDesc.dataHandle) 
  609.         AEDisposeDesc(&resultDesc);
  610.         
  611.     return(err);
  612. } // GetTHPrintFromDescriptor
  613.  
  614.  
  615. OSErr    SetMenuProperty( const AEDesc *theTokenDesc, const AEDesc *dataDesc )
  616. {
  617.     MenuPropToken    aToken;
  618.     Size            tokenSize;
  619.     OSErr            err;
  620.  
  621.     if ( typeMyMenuProp != theTokenDesc->descriptorType )
  622.         return errAEWrongDataType;
  623.  
  624.     GetRawDataFromDescriptor( theTokenDesc, (Ptr)&aToken,
  625.                                     sizeof( aToken ), &tokenSize );
  626.                                     
  627.     err = SetMenuTokenProperty( &aToken, dataDesc );
  628.  
  629.     return err;
  630. }
  631.  
  632. OSErr    SetMenuTokenProperty( MenuPropToken* theToken, const AEDesc* theData )
  633. {
  634.     MenuScriptRecPtr    aMenuRecPtr;
  635.     OSErr                err;
  636.     
  637.     switch ( theToken->tokenProperty )
  638.     {
  639.         case pScript:
  640.             aMenuRecPtr = GetMenuScriptRecPtr( theToken->token.tokenID * 32 );
  641.             if ( ! aMenuRecPtr || kOSANullScript == aMenuRecPtr->theScriptID )
  642.             {
  643.                 err = errAENoSuchObject;
  644.                 goto done;
  645.             }
  646.         
  647.             err = SetScriptDesc( theData, &aMenuRecPtr->theScriptID );
  648.             if ( noErr == err )
  649.                 aMenuRecPtr->fChanged = true;
  650.             break;
  651.             
  652.         default:
  653.             err = errAEEventNotHandled;
  654.     }
  655.  
  656. done:    
  657.     return(err);
  658. }
  659.  
  660.  
  661. OSErr    SetMenuItemProperty( const AEDesc *theTokenDesc, const AEDesc *dataDesc )
  662. {
  663.     MenuItemPropToken    aToken;
  664.     Size                tokenSize;
  665.     OSErr                err;
  666.  
  667.     if ( typeMyMenuItemProp != theTokenDesc->descriptorType )
  668.         return errAEWrongDataType;
  669.  
  670.     GetRawDataFromDescriptor( theTokenDesc, (Ptr)&aToken,
  671.                                     sizeof( aToken ), &tokenSize );
  672.                                     
  673.     err = SetMenuItemTokenProperty( &aToken, dataDesc );
  674.  
  675.     return err;
  676. }
  677.  
  678. OSErr    SetMenuItemTokenProperty( MenuItemPropToken* theToken, const AEDesc* theData )
  679. {
  680.     AEDesc                aDesc = { typeNull, NULL };
  681.     MenuScriptRecPtr    aMenuRecPtr;
  682.     Str255                aPStr;
  683.     short                aResID;
  684.     OSErr                err;
  685.  
  686.     aResID = theToken->token.tokenMenuToken.tokenID * 32 + theToken->token.tokenItem;
  687.     aMenuRecPtr = GetMenuScriptRecPtr( aResID );
  688.     
  689.     switch ( theToken->tokenProperty )
  690.     {
  691.         case pName:
  692.             err = GetPStringFromDescriptor( theData, aPStr );
  693.             if ( noErr != err ) goto done;
  694.             
  695.             SetMenuItemName( &theToken->token, aPStr );
  696.             
  697.                 // If there is a script associated then try setting the
  698.                 // itemName property.
  699.             if ( aMenuRecPtr && kOSANullScript != aMenuRecPtr->theScriptID )
  700.             {
  701.                 err = PutPStringToDescriptor( &aDesc, "\pitemname" );
  702.                 if ( noErr != err ) goto done;
  703.             
  704.                     // Ignore the error because it may not have the property
  705.                 (void)SetScriptProperty( aMenuRecPtr->theScriptID, &aDesc, theData );
  706.             }
  707.             break;
  708.     
  709.         case pScript:
  710.             if ( ! aMenuRecPtr || kOSANullScript == aMenuRecPtr->theScriptID )
  711.             {
  712.                 err = errAENoSuchObject;
  713.                 goto done;
  714.             }
  715.         
  716.             err = SetScriptDesc( theData, &aMenuRecPtr->theScriptID );
  717.             if ( noErr == err )
  718.             {
  719.                 aMenuRecPtr->fChanged = true;
  720.                 err = CheckForMenuItemName( aResID, aMenuRecPtr->theScriptID );
  721.             }
  722.             break;
  723.             
  724.         default:
  725.             err = errAEEventNotHandled;
  726.     }
  727.  
  728. done:
  729.     (void)AEDisposeDesc( &aDesc );
  730.     
  731.     return(err);
  732. }
  733.  
  734. OSErr    CheckForMenuItemName( short theResID, OSAID theOSAID )
  735. {
  736.     AEDesc        aDesc = { typeNull, NULL },
  737.                 aNameDesc = { typeNull, NULL };
  738.     Str255        aPStr;
  739.     OSErr        anErr;
  740.     
  741.     anErr = PutPStringToDescriptor( &aDesc, "\pitemname" );
  742.     if ( noErr != anErr ) goto done;
  743.  
  744.     anErr = GetScriptProperty( theOSAID, &aDesc, &aNameDesc );
  745.     if ( noErr == anErr )
  746.     {
  747.         anErr = GetPStringFromDescriptor( &aNameDesc, aPStr );
  748.         if ( noErr != anErr ) goto done;
  749.     
  750.         SetMenuItemText( MenuHandleFromMenuID( theResID / 32 ), theResID % 32, aPStr );
  751.     }
  752.     else
  753.         anErr = noErr;    // Just doesn't have the property so no error
  754.  
  755. done:    
  756.     return anErr;
  757. }
  758.  
  759.  
  760. // ----------------------------------------------------------------------
  761. //    Name:         SetTextProperty
  762. //    Purpose:    Sets the text property specfied by theTextPropToken to
  763. //                that in dataDesc.
  764. // ----------------------------------------------------------------------
  765.      
  766. OSErr    SetTextProperty(const AEDesc *tokenDesc, const AEDesc *dataDesc)
  767. {
  768.     DPtr              theDoc;
  769.     Str255            name;
  770.     short             theSize;
  771.     Style             onStyle;
  772.     Style             offStyle;
  773.     TextPropToken     theTextPropToken;
  774.     AEDesc            newDesc = {typeNull, NULL},
  775.                     nullDesc = {typeNull, NULL},
  776.                     ignoreResult = {typeNull, NULL};
  777.     Size              tokenSize;
  778.     OSErr             err;
  779.  
  780.       err = AECoerceDesc(tokenDesc, typeMyTextProp, &newDesc);
  781.       if (noErr != err) goto done;
  782.  
  783.     GetRawDataFromDescriptor(&newDesc, (Ptr)&theTextPropToken,
  784.                                     sizeof(theTextPropToken), &tokenSize);
  785.         
  786.     theDoc = DPtrFromWindowPtr(theTextPropToken.tokenTextToken.tokenWindow);
  787.     theDoc->dirty = true;
  788.     
  789.     switch (theTextPropToken.tokenProperty)
  790.     {
  791.         case pText:
  792.         case pContents:
  793.             err = CreateAtTextToken(cText, dataDesc, &(theTextPropToken.tokenTextToken),
  794.                                                                 &nullDesc, &ignoreResult);
  795.             break;
  796.             
  797.         case pFont:
  798.             err = GetPStringFromDescriptor(dataDesc, name);
  799.             if (noErr != err) goto done;
  800.             err = SetFontOfTextToken(&theTextPropToken.tokenTextToken, name);
  801.             break;
  802.             
  803.         case pPointSize:    
  804.             err = GetIntegerFromDescriptor(dataDesc, &theSize);
  805.             if (noErr != err) goto done;
  806.             err = SetSizeOfTextToken(&theTextPropToken.tokenTextToken, theSize);
  807.             break;
  808.             
  809.         case pTextStyles:
  810.             onStyle  = 0;
  811.             offStyle = 0;
  812.             
  813.             err = GetTextStyles(dataDesc, &onStyle, &offStyle);
  814.             if (noErr != err) goto done;
  815.  
  816.             if (onStyle & offStyle != 0)
  817.                 err = errAEEventFailed;
  818.             else
  819.                 err = SetStyleOfTextToken(&theTextPropToken.tokenTextToken, onStyle, offStyle);
  820.             break;
  821.         
  822.         default:
  823.             err = errAEWrongDataType;
  824.     }
  825.  
  826. done:
  827.     (void)AEDisposeDesc(&newDesc);
  828.             
  829.     return(err);
  830. } // SetTextProperty
  831.  
  832.     
  833. short ItemForNamedFont(Str255 theName)
  834. {
  835.     Str255  itemName;
  836.     short   limit;
  837.  
  838.     limit = CountMItems(myMenus[fontM]);
  839.     while (limit>0)
  840.     {
  841.         GetItem(myMenus[fontM],limit, itemName);
  842.         if (IUEqualString(theName, itemName)==0) 
  843.             return(limit);
  844.         else
  845.             limit--;
  846.     }
  847.     return(0);
  848. } // ItemForNamedFont
  849.  
  850.  
  851. // -----------------------------------------------------------------------
  852. //    Name:         SetFontOfTextToken
  853. //    Purpose:    Sets the font of the text specified by theToken to 
  854. //                the font in name.
  855. // -----------------------------------------------------------------------
  856.      
  857. OSErr    SetFontOfTextToken(TextToken* theToken, Str255 name)
  858. {
  859.     DPtr        docPtr;
  860.     TextToken    oldSelection;
  861.     short        theNumber,
  862.                 theItem;
  863.     TextStyle    newStyle;
  864.     Boolean        fCurrentSelection;
  865.     OSErr        err;
  866.  
  867.     docPtr = DPtrFromWindowPtr(theToken->tokenWindow);
  868.     
  869.     if (!docPtr) return(errAENoSuchObject);
  870.         
  871.                 // ignore theNumber result
  872.     err = GetWindowSelection(theToken->tokenWindow, &oldSelection, &theNumber);
  873.     if (noErr != err) goto done;
  874.     
  875.     if (memcmp(theToken, &oldSelection, sizeof(TextToken)))
  876.     {
  877.         fCurrentSelection = false;
  878.         err = SelectTextToken(theToken);    // Only set the selection if it's different
  879.         if (noErr != err) goto done;
  880.     }
  881.     else
  882.         fCurrentSelection = true;
  883.             
  884.     GetFNum(name, &theNumber);
  885.     
  886.     theItem = ItemForNamedFont(name); // returns 0 if failed - i.e. SystemFont
  887.     
  888.     if (gFontMItem)
  889.         CheckItem(myMenus[fontM], gFontMItem, false);
  890.     
  891.     gFontMItem = theItem;
  892.     CheckItem(myMenus[fontM], gFontMItem, true);
  893.     
  894.     docPtr->theFont = theNumber;
  895.         
  896.     newStyle.tsFont = theNumber;
  897.     TESetStyle(doFont, &newStyle, true, docPtr->theText); 
  898.     
  899.     AdjustScrollbars(docPtr, false);
  900.     DrawPageExtras(docPtr);
  901.     docPtr->dirty = true;
  902.     
  903.     if (! fCurrentSelection)
  904.         err = SelectTextToken(&oldSelection);
  905.  
  906. done:    
  907.     return(err);
  908. } // SetFontOfTextToken
  909.     
  910. // -----------------------------------------------------------------------
  911. //    Name:             SetSizeOfTextToken
  912. //    Purpose:        Sets the size of the text specified by theToken to 
  913. //                    the size in theSize.
  914. // -----------------------------------------------------------------------
  915.      
  916. OSErr    SetSizeOfTextToken(TextToken* theToken, short theSize)
  917. {
  918.     DPtr        docPtr;
  919.     TextToken    oldSelection;
  920.     TextStyle    newStyle;
  921.     short        ignore;
  922.     Boolean        fCurrentSelection;
  923.     OSErr        err;
  924.  
  925.     docPtr = DPtrFromWindowPtr(theToken->tokenWindow);
  926.     
  927.     if (!docPtr) return(errAENoSuchObject);
  928.         
  929.                 // Save the old selection
  930.     err = GetWindowSelection(theToken->tokenWindow, &oldSelection, &ignore);
  931.     if (noErr != err) goto done;
  932.     
  933.     if (memcmp(theToken, &oldSelection, sizeof(TextToken)))
  934.     {
  935.         fCurrentSelection = false;
  936.         err = SelectTextToken(theToken);
  937.         if (noErr != err) goto done;
  938.     }
  939.     else
  940.         fCurrentSelection = true;
  941.                             
  942.     docPtr->theSize = theSize;
  943.     
  944.     newStyle.tsSize = theSize;
  945.     TESetStyle(doSize, &newStyle, true, docPtr->theText); 
  946.     
  947.     AdjustScrollbars(docPtr, false);
  948.     DrawPageExtras(docPtr);
  949.     docPtr->dirty = true;
  950.     
  951.     if (! fCurrentSelection)    // If we reset the selection we may loose the
  952.         err = SelectTextToken(&oldSelection);    // Size or style just set
  953.  
  954. done:    
  955.     return(err);
  956. } // SetSizeOfTextToken
  957.     
  958. // ------------------------------------------------------------------------
  959. //    Name:             SetStyleOfTextToken
  960. //    Purpose:        Sets the style of the text specified by theToken to 
  961. //                    the style in theStyle.
  962. // ------------------------------------------------------------------------
  963.      
  964. OSErr    SetStyleOfTextToken(TextToken* theToken, Style onStyle, Style offStyle)
  965. {
  966.     DPtr        docPtr;
  967.     TextToken    oldSelection;
  968.     TextStyle    newStyle;
  969.     short        mode;
  970.     Boolean        wasContinuous;
  971.     short        ignore;
  972.     Boolean        fCurrentSelection;
  973.     OSErr        err;
  974.  
  975.     docPtr = DPtrFromWindowPtr(theToken->tokenWindow);
  976.     
  977.     if (!docPtr) return(errAENoSuchObject);
  978.         
  979.                 // Save the old selection
  980.     err = GetWindowSelection(theToken->tokenWindow, &oldSelection, &ignore);
  981.     if (noErr != err) goto done;
  982.     
  983.     if (memcmp(theToken, &oldSelection, sizeof(TextToken)))
  984.     {
  985.         fCurrentSelection = false;
  986.         err = SelectTextToken(theToken);
  987.         if (noErr != err) goto done;
  988.     }
  989.     else
  990.         fCurrentSelection = true;
  991.                             
  992.     docPtr->theStyle = onStyle;
  993.     
  994.         // Check to see if off styles are on for whole selection
  995.     mode = doFace;
  996.     
  997.     wasContinuous = TEContinuousStyle(&mode, &newStyle, docPtr->theText);
  998.     if ((newStyle.tsFace & offStyle) != offStyle) // not off styles are on for all
  999.     {
  1000.             // switch on across board so that toggle off will clear all
  1001.         newStyle.tsFace  = offStyle - (newStyle.tsFace & offStyle);
  1002.         TESetStyle(doFace+doToggle, &newStyle, false, docPtr->theText); 
  1003.     }
  1004.         
  1005.     newStyle.tsFace  = offStyle;
  1006.     TESetStyle(doFace+doToggle, &newStyle,(onStyle==0), docPtr->theText); // toggle all to off
  1007.     
  1008.     mode = doFace;
  1009.     if (onStyle)
  1010.     {
  1011.         wasContinuous = TEContinuousStyle(&mode, &newStyle, docPtr->theText);
  1012.         if ((newStyle.tsFace & onStyle) != onStyle) // are they on for only a few chars
  1013.         { 
  1014.                 // Need to make all chars have these characteristics
  1015.             newStyle.tsFace = onStyle - (newStyle.tsFace & onStyle); // take out those continuous
  1016.             TESetStyle(doFace+doToggle, &newStyle, true, docPtr->theText);
  1017.         }
  1018.         else
  1019.             TESetStyle(0, &newStyle, true, docPtr->theText); // Just Draw it, no changes
  1020.     }
  1021.         
  1022.     AdjustScrollbars(docPtr, false);
  1023.     DrawPageExtras(docPtr);
  1024.     docPtr->dirty = true;
  1025.     
  1026.     if (! fCurrentSelection)
  1027.         err = SelectTextToken(&oldSelection);
  1028.  
  1029. done:    
  1030.     return(err);
  1031. } // SetStyleOfTextToken
  1032.  
  1033.     
  1034. OSErr    GetTextStyles(const AEDesc *dataDesc, Style *onStyles, Style *offStyles)
  1035. {
  1036.     OSErr      myErr;
  1037.     AEDescList textSDesc = { typeNull, NULL };
  1038.     AEDescList onDesc = { typeNull, NULL };
  1039.     AEDescList offDesc = { typeNull, NULL };
  1040.     Boolean    hadPlain;
  1041.     
  1042.     *onStyles  = 0;
  1043.     *offStyles = 0;
  1044.     
  1045.     myErr = AECoerceDesc(dataDesc, typeAERecord, &textSDesc);
  1046.     
  1047.     if (myErr==noErr)
  1048.       myErr = AEGetKeyDesc(&textSDesc, keyAEOnStyles, typeAEList, &onDesc);
  1049.     
  1050.     if (myErr==noErr)
  1051.       myErr = AEGetKeyDesc(&textSDesc, keyAEOffStyles, typeAEList, &offDesc);
  1052.     
  1053.     if (myErr==noErr)
  1054.         myErr = MakeStyleFromAEList(&onDesc,  onStyles, &hadPlain);
  1055.     
  1056.     if (hadPlain)
  1057.         *offStyles = bold+italic+underline+outline+shadow+condense+extend;
  1058.     else
  1059.     {
  1060.         if (myErr==noErr)
  1061.             myErr = MakeStyleFromAEList(&offDesc, offStyles, &hadPlain);
  1062.         
  1063.         if (hadPlain)
  1064.             myErr = errAEEventFailed;
  1065.     }
  1066.         
  1067.     (void)AEDisposeDesc(&textSDesc);
  1068.     (void)AEDisposeDesc(&onDesc);
  1069.     (void)AEDisposeDesc(&offDesc);
  1070.     
  1071.     return(myErr);
  1072. } // GetTextStyles
  1073.  
  1074. // -----------------------------------------------------------------------
  1075. //    Name:         AddDescStyleItem
  1076. //    Purpose:    Adds the kAEXXXX style to theStyle.
  1077. // -----------------------------------------------------------------------
  1078.      
  1079. void    AddDescStyleItem(DescType theDesc, Style *theStyle)
  1080. {
  1081.     if (theDesc == kAEBold)
  1082.         *theStyle = *theStyle+bold;
  1083.     else
  1084.     if (theDesc == kAEItalic)
  1085.         *theStyle = *theStyle+italic;
  1086.     else
  1087.     if (theDesc == kAEUnderline)
  1088.         *theStyle = *theStyle+underline;
  1089.     else
  1090.     if (theDesc == kAEOutline)
  1091.         *theStyle = *theStyle+outline;
  1092.     else
  1093.     if (theDesc == kAEShadow)
  1094.         *theStyle = *theStyle+shadow;
  1095.     else
  1096.     if (theDesc == kAECondensed)
  1097.         *theStyle = *theStyle+condense;
  1098.     else
  1099.     if (theDesc == kAEExpanded)
  1100.         *theStyle = *theStyle+extend;
  1101.     else
  1102.     if (theDesc == kAEPlain)
  1103.         *theStyle = 0;
  1104. } // AddDescStyleItem
  1105.     
  1106. OSErr    MakeStyleFromAEList(const AEDescList *styleList, Style *theStyle, Boolean *hadPlain)
  1107. {
  1108.     OSErr     myErr;
  1109.     DescType  styleDesc;
  1110.     long      itemsInList;
  1111.     long      actSize;
  1112.     AEKeyword keywd;
  1113.     DescType  typeCode;
  1114.         
  1115.     *hadPlain = false;
  1116.     *theStyle = 0;
  1117.     
  1118.     myErr = AECountItems(styleList, &itemsInList);
  1119.     while (itemsInList>0)
  1120.         if (myErr==noErr)
  1121.         {
  1122.             myErr  = AEGetNthPtr(styleList, itemsInList, typeEnumerated, &keywd,
  1123.                                 &typeCode, (Ptr)&styleDesc, sizeof(styleDesc), &actSize);
  1124.             
  1125.             AddDescStyleItem(styleDesc, theStyle);
  1126.             
  1127.             if (styleDesc == kAEPlain) 
  1128.             {
  1129.                 itemsInList = 0;
  1130.                 *hadPlain = true;
  1131.             }
  1132.             else
  1133.               itemsInList--;
  1134.         }
  1135.             
  1136.     return(myErr);
  1137. } // MakeStyleFromAEList
  1138.